#include <GL3\gl3.h>
#include <GL3\gl3w.h>
#include <GL\freeglut.h>
#include <string>

#include "Kernel\KernelManager.h"

void display();
void reshape(int w, int h);
void keyboard(unsigned char key, int x, int y);

int main(int argc, char **argv)
{
	/////////////////////////////////////////
	// CONFIG INITIALIZING
	/////////////////////////////////////////
	std::string base_dir = argv[0];
	base_dir = base_dir.substr(0, base_dir.find_last_of("\\"));
	base_dir = base_dir.substr(0, base_dir.find_last_of("\\"));
	base_dir += "\\resources\\";

	auto kernel = Kernel::Manager::getSingleton();
	if(Kernel::Manager::getSingleton()->configure(base_dir) != 0)
		return -1;

	//////////////////////////////////////////
	// GLUT INITIALIZING
	//////////////////////////////////////////
	glutInit(&argc, argv);
	glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
	glutInitContextVersion (4, 2);
	glutInitContextFlags (GLUT_FORWARD_COMPATIBLE | GLUT_DEBUG);
	glutInitContextProfile(GLUT_CORE_PROFILE);

	glutInitWindowSize (kernel->getWidth(), kernel->getHeight()); 
	glutInitWindowPosition (100, 100);
	glutCreateWindow (argv[0]);

	//////////////////////////////////////////
	// GL3W INITIALIZING
	//////////////////////////////////////////
	GLenum gl3wInitErr = gl3wInit();
	if(gl3wInitErr)
		throw std::runtime_error("Failed to initialize OpenGL!");
	if(gl3wIsSupported(3,3) == false)
		throw std::runtime_error("OpenGL 3.3 is not supported!");

	//////////////////////////////////////////
	// KERNEL INITIALIZING
	//////////////////////////////////////////
	if(kernel->initialize(argc, argv))
		return -1;

	//////////////////////////////////////////
	// GLUT FUNCTOR INITIALIZING
	//////////////////////////////////////////
	glutIdleFunc(display);
	glutDisplayFunc(display); 
	glutReshapeFunc(reshape);
	glutKeyboardFunc(keyboard);

	//////////////////////////////////////////
	// HEARTBEAT
	//////////////////////////////////////////
	glutMainLoop();

	return 0;
}

void display()
{
	auto kernel = Kernel::Manager::getSingleton();
	kernel->update(1.0f);
	kernel->render();
	glutSwapBuffers();
}

void reshape(int w, int h)
{
}

void keyboard(unsigned char key, int x, int y)
{
	Kernel::Manager::getSingleton()->input(key,x,y);
}
